package com.shuziren.service.util;


import com.shuziren.domain.dto.Resume;
import com.shuziren.service.ResumeRepository;
import lombok.extern.slf4j.Slf4j;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
public class FileParser {

    @Autowired
    private ResumeRepository resumeRepository;

    public Resume parseFile(File file) throws IOException {
        log.info("开始解析文件: {}", file.getName());
        String fileName = file.getName().toLowerCase();
        
        try {
            Resume resume;
            if (fileName.endsWith(".docx")) {
                log.info("解析Word文档");
                resume = parseDocx(file);
            } else if (fileName.endsWith(".pdf")) {
                log.info("解析PDF文档");
                resume = parsePdf(file);
            } else {
                log.warn("不支持的文件类型: {}", fileName);
                return null;
            }
            
            // 保存到数据库
            if (resume != null) {
                log.info("开始保存简历到数据库");
                resume = resumeRepository.save(resume);
                log.info("简历保存成功，ID: {}", resume.getId());
            }
            
            return resume;
        } catch (Exception e) {
            log.error("文件解析失败: {}", e.getMessage(), e);
            throw new IOException("文件解析失败: " + e.getMessage(), e);
        }
    }

    private Resume parseDocx(File file) throws IOException {
        log.info("开始解析Word文档: {}", file.getName());
        try (FileInputStream fis = new FileInputStream(file)) {
            log.info("创建XWPFDocument对象");
            XWPFDocument document = new XWPFDocument(fis);
            
            // 获取文档总页数
            int totalPages = document.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();
            log.info("Word文档总页数: {}", totalPages);
            
            // 获取所有段落
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            log.info("文档段落数: {}", paragraphs.size());
            
            // 构建完整文本
            StringBuilder fullText = new StringBuilder();
            int currentPage = 1;
            int paragraphsPerPage = paragraphs.size() / totalPages;
            
            for (int i = 0; i < paragraphs.size(); i++) {
                XWPFParagraph paragraph = paragraphs.get(i);
                String text = paragraph.getText();
                
                // 添加页面分隔标记
                if (i % paragraphsPerPage == 0 && i > 0) {
                    currentPage++;
                    fullText.append("\n--- 第").append(currentPage).append("页 ---\n");
                }
                
                if (text != null && !text.trim().isEmpty()) {
                    // 处理换行和空格
                    text = text.replaceAll("\\s+", " ").trim();
                    fullText.append(text).append("\n");
                }
            }
            
            // 添加最后一页结束标记
            fullText.append("\n--- 第").append(currentPage).append("页结束 ---\n");
            
            String text = fullText.toString();
            log.info("Word文档内容长度: {} 字符", text.length());
            log.info("文档内容预览: {}", text);
            return extractResumeInfo(text);
        } catch (Exception e) {
            log.error("Word文档解析失败: {}", e.getMessage(), e);
            throw new IOException("Word文档解析失败: " + e.getMessage(), e);
        }
    }

    private Resume parsePdf(File file) throws IOException {
        log.info("开始解析PDF文档: {}", file.getName());
        try (PDDocument document = PDDocument.load(file)) {
            int totalPages = document.getNumberOfPages();
            log.info("PDF文档总页数: {}", totalPages);
            
            // 创建PDFTextStripper对象
            PDFTextStripper stripper = new PDFTextStripper();
            
            // 设置提取所有页面
            stripper.setStartPage(1);
            stripper.setEndPage(totalPages);
            
            // 设置段落分隔符
            stripper.setParagraphStart("\n");
            stripper.setParagraphEnd("\n");
            
            // 设置页面分隔符
            stripper.setPageStart("\n--- 第{1}页 ---\n");
            stripper.setPageEnd("\n--- 第{3}页结束 ---\n");
            
            // 提取文本
            String text = stripper.getText(document);
            // 处理换行和空格
            text = text.replaceAll("\\s+", " ").trim();
            log.info("PDF文档内容长度: {} 字符", text.length());
            log.info("文档内容预览: {}", text);
            return extractResumeInfo(text);
        } catch (Exception e) {
            log.error("PDF文档解析失败: {}", e.getMessage(), e);
            throw new IOException("PDF文档解析失败: " + e.getMessage(), e);
        }
    }

    private Resume extractResumeInfo(String text) {
        log.info("开始提取简历信息");
        Resume resume = new Resume();
        
        try {
            // 使用正则表达式提取信息，改进匹配模式
            String name = extractInfo(text, "(?:姓名|名字|Name)[:：]\\s*([^\\n]+)");
            log.info("提取姓名: {}", name);
            resume.setName(name);
            
            String gender = extractInfo(text, "(?:性别|Gender)[:：]\\s*([^\\n]+)");
            log.info("提取性别: {}", gender);
            resume.setGender(gender);
            
            String ageStr = extractInfo(text, "(?:年龄|Age)[:：]\\s*([^\\n]+)");
            log.info("提取年龄: {}", ageStr);
            resume.setAge(parseAge(ageStr));
            
            String phone = extractInfo(text, "(?:电话|手机|联系方式|Phone|Mobile)[:：]\\s*([^\\n]+)");
            log.info("提取电话: {}", phone);
            resume.setPhone(phone);
            
            String email = extractInfo(text, "(?:邮箱|电子邮件|Email)[:：]\\s*([^\\n]+)");
            log.info("提取邮箱: {}", email);
            resume.setEmail(email);
            
            String education = extractInfo(text, "(?:学历|教育程度|Education)[:：]\\s*([^\\n]+)");
            log.info("提取学历: {}", education);
            resume.setEducation(education);
            
            String school = extractInfo(text, "(?:毕业院校|学校|院校|School)[:：]\\s*([^\\n]+)");
            log.info("提取毕业院校: {}", school);
            resume.setSchool(school);
            
            String major = extractInfo(text, "(?:专业|Major)[:：]\\s*([^\\n]+)");
            log.info("提取专业: {}", major);
            resume.setMajor(major);
            
            // 改进工作经验提取
            String experience = extractInfo(text, "(?:工作经验|工作经历|Experience)[:：]\\s*([\\s\\S]+?)(?=(?:项目经历|技能|自我评价|$))");
            if (experience == null) {
                // 尝试匹配公司名称和时间
                experience = extractInfo(text, "([^\\n]+公司\\s*\\d{4}\\.\\d{1,2}-\\d{4}\\.\\d{1,2}[\\s\\S]+?)(?=(?:项目经历|技能|自我评价|$))");
            }
            log.info("提取工作经验: {}", experience != null ? "已提取" : "未找到");
            resume.setExperience(experience);
            
            // 改进项目经历提取
            String projectExperience = extractInfo(text, "(?:项目经历|项目经验)[:：]\\s*([\\s\\S]+?)(?=(?:个人评价|$))");
            if (projectExperience == null) {
                // 尝试匹配项目列表格式（以·开头的格式）
                projectExperience = extractInfo(text, "(?:项目经历|项目经验)[:：]\\s*(·[\\s\\S]+?)(?=(?:个人评价|$))");
            }
            if (projectExperience == null) {
                // 尝试匹配项目标题格式
                projectExperience = extractInfo(text, "(?:项目名称|项目)[:：]\\s*(·[\\s\\S]+?)(?=(?:个人评价|$))");
            }
            if (projectExperience == null) {
                // 尝试匹配项目描述格式
                projectExperience = extractInfo(text, "(?:项目描述|项目职责)[:：]\\s*(·[\\s\\S]+?)(?=(?:个人评价|$))");
            }
            if (projectExperience == null) {
                // 尝试直接匹配项目内容（以·开头的格式）
                projectExperience = extractInfo(text, "(·[\\s\\S]+?)(?=(?:个人评价|$))");
            }
            log.info("提取项目经历: {}", projectExperience != null ? "已提取" : "未找到");
            resume.setProjectExperience(projectExperience);
            
            // 改进技能提取
            String skills = extractInfo(text, "(?:专业技能)[:：]\\s*([\\s\\S]+?)(?=(?:工作经验|项目经历|个人评价|$))");
            if (skills == null) {
                // 尝试匹配技能列表格式
                skills = extractInfo(text, "(?:专业技能)[:：]\\s*([^;\\n]+(?:;[^;\\n]+)*)(?=(?:工作经验|项目经历|个人评价|$))");
            }
            if (skills == null) {
                // 尝试匹配技术栈格式
                skills = extractInfo(text, "(?:技术栈|技术技能)[:：]\\s*([^;\\n]+(?:;[^;\\n]+)*)(?=(?:工作经验|项目经历|个人评价|$))");
            }
            if (skills == null) {
                // 尝试匹配技能点格式
                skills = extractInfo(text, "(?:掌握技能|熟悉技能|精通技能)[:：]\\s*([^;\\n]+(?:;[^;\\n]+)*)(?=(?:工作经验|项目经历|个人评价|$))");
            }
            if (skills == null) {
                // 尝试直接匹配技能内容
                skills = extractInfo(text, "(?:熟悉[^\\n]+;[^\\n]+;[^\\n]+;[^\\n]+;[^\\n]+;[^\\n]+;[^\\n]+;[^\\n]+)(?=(?:工作经验|项目经历|个人评价|$))");
            }
            log.info("提取技能: {}", skills != null ? "已提取" : "未找到");
            resume.setSkills(skills);
            
            // 改进自我评价提取
            String selfEvaluation = extractInfo(text, "(?:个人评价)[:：]\\s*([\\s\\S]+?)$");
            if (selfEvaluation == null) {
                // 尝试匹配数字列表格式的自我评价
                selfEvaluation = extractInfo(text, "(?:个人评价)[:：]\\s*(\\d+\\.[\\s\\S]+?)(?=(?:$|\\n\\s*$))");
            }
            if (selfEvaluation == null) {
                // 尝试匹配个人总结格式
                selfEvaluation = extractInfo(text, "(?:个人总结|个人简介)[:：]\\s*([\\s\\S]+?)$");
            }
            if (selfEvaluation == null) {
                // 尝试匹配其他描述格式
                selfEvaluation = extractInfo(text, "(?:个人特点|个人优势)[:：]\\s*([\\s\\S]+?)$");
            }
            if (selfEvaluation == null) {
                // 尝试直接匹配评价内容（以数字开头的列表）
                selfEvaluation = extractInfo(text, "(\\d+\\.[\\s\\S]+?)(?=(?:$|\\n\\s*$))");
            }
            log.info("提取自我评价: {}", selfEvaluation != null ? "已提取" : "未找到");
            resume.setSelfEvaluation(selfEvaluation);
            
            return resume;
        } catch (Exception e) {
            log.error("简历信息提取失败: {}", e.getMessage(), e);
            throw new RuntimeException("简历信息提取失败: " + e.getMessage(), e);
        }
    }

    private String extractInfo(String text, String pattern) {
        try {
            Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
            Matcher m = p.matcher(text);
            if (m.find()) {
                String result = m.group(1).trim();
                log.debug("匹配成功 - 模式: {}, 结果: {}", pattern, result);
                return result;
            }
            log.debug("匹配失败 - 模式: {}", pattern);
            return null;
        } catch (Exception e) {
            log.error("正则表达式匹配失败: {}", e.getMessage());
            return null;
        }
    }

    private Integer parseAge(String ageStr) {
        if (ageStr == null) return null;
        try {
            // 提取数字
            Pattern pattern = Pattern.compile("\\d+");
            Matcher matcher = pattern.matcher(ageStr);
            if (matcher.find()) {
                return Integer.parseInt(matcher.group());
            }
            return null;
        } catch (NumberFormatException e) {
            log.warn("年龄解析失败: {}", ageStr);
            return null;
        }
    }
} 